package ch.simplix.android.repetitive.implementation;

import java.util.concurrent.TimeUnit;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import ch.simplix.android.repetitive.definition.RepeaterAction;
import ch.simplix.android.repetitive.definition.RepeaterStrategy;

/**
 * This {@link RepeaterStrategy} is very usable for precise repetition-delays
 * between 15minutes and more. The action is called 'real time'.
 * 
 * @author SimpliX
 * 
 */
public class AlarmRepeaterStrategy extends ARepeaterStrategy {
	// Get the AlarmManager service
	private AlarmManager am;
	private PendingIntent sender;
	public static final String ACTION_REPEAT = "ch.simplix.android.repetitive.service.implementation.AlarmRepeaterStrategy.ACTION_REPEAT";
	private IntentFilter alarmRepeater;
	private AlarmHandler alarmHandler;

	/*
	 * (non-Javadoc)
	 * 
	 * @see ch.simplix.android.repetitive.service.RepeaterStrategy#isRunning()
	 */
	@Override
	public boolean isRunning() {
		return sender != null;
	}

	public AlarmRepeaterStrategy(RepeaterAction repeaterAction) {
		super(repeaterAction);
		this.alarmHandler = new AlarmHandler();
	}

	/**
	 * Android probably never calls this method. So 'we have to' call it.
	 * 
	 * @see ch.simplix.android.repetitive.service.RepeaterStrategy#finalize()
	 */
	@Override
	public void finalize() {
		stopTimedRepetition();
		if (alarmRepeater == null)
			return;
		if (getRepeaterAction() == null)
			return;
		getRepeaterAction().getContext().unregisterReceiver(alarmHandler);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * ch.simplix.android.repetitive.service.RepeaterStrategy#startTimedRepetition
	 * ()
	 */
	@Override
	public void startTimedRepetition() {
		prepareRepetition();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * ch.simplix.android.repetitive.service.RepeaterStrategy#stopTimedRepetition
	 * ()
	 */
	@Override
	public void stopTimedRepetition() {
		if (sender == null)
			return;
		AlarmManager am = getAlarmManager();
		if (am == null)
			return;
		am.cancel(sender);
		sender = null;
		super.setUpdateInterval(0, TimeUnit.SECONDS);
	}

	/**
	 * Gets the alarmingManager
	 */
	protected AlarmManager getAlarmManager() {
		if (am == null)
			this.am = (AlarmManager) getRepeaterAction().getContext()
					.getSystemService(Context.ALARM_SERVICE);
		return am;
	}

	@Override
	protected void prepareRepetition() {
		// Connect the BroadcastReceiver (ourself)
		if (alarmRepeater == null) {
			alarmRepeater = new IntentFilter(
					AlarmRepeaterStrategy.ACTION_REPEAT);
			getRepeaterAction().getContext().registerReceiver(alarmHandler,
					alarmRepeater);
		}
		Intent intent = new Intent(ACTION_REPEAT);
		// In reality, you would want to have a static variable for the
		// request code instead of 0
		sender = PendingIntent.getBroadcast(getRepeaterAction().getContext(),
				0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
		setAlarmRepeating(sender);
	}

	protected void setAlarmRepeating(PendingIntent sender) {
		getAlarmManager().setRepeating(AlarmManager.RTC_WAKEUP,
				getNextRepetitionInMillis(), getUpdateIntervalInMillis(),
				sender);
	}

	class AlarmHandler extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (isRunning()) {
				act();
			}
		}

	}
}
